﻿'Imports System.Windows.Forms
Imports System.ComponentModel
<Serializable()> Public Class FEntity

    Public Sub New(ByVal s As String, ByVal pl As MapWinGIS.Point(), ByVal d As String)

        sn = s
        ptlist = pl
        desc = d



    End Sub



    Public Sub New()


    End Sub

    Public sn As String
    <NonSerialized()> Public ptlist() As MapWinGIS.Point
    Public desc As String

End Class


'这里的类，假定层的第一个属性，是名称信息
<Serializable()> Public MustInherit Class EditableShapeLayer
    Inherits Layer


    Public Sub New(ByVal ln As String, ByVal tl As BaseTool)
        MyBase.new(ln, "")

        m_drawTool = tl

        m_bReadOnly = False

        '最关键的一点，指明此类是可以编辑的类,这里的设计可能有点差，但在有更好方法前，就这么用吧
        m_Editalbe = True





        '初始化内部的一些信息
        AddHandler m_drawTool.endDrawing, AddressOf Me.EntityDrawEnd
        ' m_drawTool.SetMapRef(mapwin)


    End Sub

    '试验中间是否可以更换辅助绘图工具
    Public Sub ChangeDrawTool(ByVal tl As BaseTool)



        RemoveHandler m_drawTool.endDrawing, AddressOf Me.EntityDrawEnd


        m_drawTool = tl

        AddHandler m_drawTool.endDrawing, AddressOf Me.EntityDrawEnd

        m_drawTool.SetMapRef(mapwin)


    End Sub

    '这些都是为了讨厌的VB事件逻辑啊
    Protected Sub New( _
      ByVal info As System.Runtime.Serialization.SerializationInfo, _
      ByVal context As System.Runtime.Serialization.StreamingContext)

        MyBase.New(info, context)

    End Sub



    '关于关闭编辑的子程序
    Protected Overrides Sub setNoEdditingSubRoute()
        MyBase.setNoEdditingSubRoute()

        m_drawTool.CancelDraw()

    End Sub

    '定义内部调用的字段
    Protected m_drawTool As BaseTool

    Protected m_bReadOnly As Boolean

    '关于图形选择后，编辑移动的研究
    Protected dicKeyPts As New Dictionary(Of String, FEntity) '关键节点

    Public Function GetEntity(ByVal sn As String) As FEntity
        If dicKeyPts.ContainsKey(sn) Then
            Return dicKeyPts.Item(sn)
        Else

            Return Nothing
        End If

    End Function



    <NonSerialized()> Protected m_Exents As MapWinGIS.Extents
    Protected m_SColor As UInt32 = 1000 '实体选中后的颜色

    Protected m_selShapes As New List(Of String)

    <Browsable(False)> _
    Public Property SColorProperty() As UInt32  '实体选中后的颜色;
        Get
            Return m_SColor
        End Get
        Set(ByVal value As UInt32)  '实体选中后的颜色;)
            m_SColor = value
        End Set
    End Property


    '公用的一些标准函数
    Public MustOverride Function AddEntity(ByVal sn As String, ByVal ptlist() As MapWinGIS.Point, ByVal desc As String) As Integer

    Public MustOverride Sub AddEntityRange(ByVal lst As List(Of FEntity))



    Public Sub RemoveEntity(ByVal sn As String)
        If m_bReadOnly Then
            Return
        End If

        dicKeyPts.Remove(sn)

        'If m_selShapes.Contains(sn) Then
        '    m_selShapes.Remove(sn)
        'End If

        Dim iShape As Integer = Me.GetShapeIdByFieldString(sn, 0)
        If (iShape <> -1) Then
            Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

            sf.StartEditingShapes()


            sf.EditDeleteShape(iShape)

            sf.StopEditingShapes()


        End If

        mapwin.Redraw()


    End Sub

    Public Sub RemoveAllEntity()

        dicKeyPts.Clear()

        Dim sfData As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)



        sfData.StartEditingShapes(True)


        'While sfData.NumShapes > 0
        '    sfData.EditDeleteShape(0)
        'End While
        sfData.EditClear()

        sfData.StopEditingShapes()

        mapwin.Redraw()

    End Sub

 

    ''' <summary>
    ''' 没有真正的实现，请不要使用此函数
    ''' </summary>
    ''' <param name="sn"></param>
    ''' <param name="ptlist"></param>
    ''' <remarks></remarks>
    Public Sub ModifyEntity(ByVal sn As String, ByVal ptlist() As MapWinGIS.Point)
        If m_bReadOnly Then
            Return
        End If

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)
        Dim iShape As Integer = Me.GetShapeIdByFieldString(sn, 0)

        '删除原有的点
        While sf.Shape(iShape).numPoints > 0
            sf.Shape(iShape).DeletePoint(0)
        End While


        '添加新的点，效率上可能差点
        Dim pIndex As Integer

        For i As Integer = 0 To ptlist.Length - 1

            sf.Shape(iShape).InsertPoint(ptlist(i), pIndex)

        Next




       


    End Sub

    Public Sub SetDrawEntity(ByVal bDraw As Boolean)

        If bDraw Then
            m_bEditing = bDraw
            mapwin.MapCursor = MapWinGIS.tkCursor.crsrCross
        Else
            m_bEditing = bDraw
            mapwin.MapCursor = MapWinGIS.tkCursor.crsrMapDefault
        End If


    End Sub

    Protected Overrides Sub DrawText()

        mapwin.ClearLabels(m_iLayer)

        mapwin.LayerFont(m_iLayer, m_TextFont.Name, m_TextFont.Size)


        If m_bShowText Then

            Dim sfData As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

            Dim str As String

            Dim pt As MapWinGIS.Point
            Dim uclr As UInt32 = RGB(m_TextColor.R, m_TextColor.G, m_TextColor.B)

            For iShape As Integer = 0 To sfData.NumShapes - 1

                If sfData.NumFields > 0 Then

                    '注意最新的软件更新，已经使0作为ID，1作为显示名称
                    str = sfData.CellValue(1, iShape)

                    pt = sfData.QuickPoint(iShape, 0)

                    mapwin.AddLabelEx(m_iLayer, str, uclr, pt.x, pt.y, MapWinGIS.tkHJustification.hjCenter, 0)

                End If


            Next







        End If

    End Sub

    '为同一图层，绘制多种源的能力，而特殊设计的标志位
    Dim shapeDesc As String = "NoDef"

    ''' <summary>
    ''' 默认值是“NoDef”，你可以通过自己设定值，来保证得到绘制图形的一些自定义性质
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    <Browsable(False)> _
    Public Property SelfDefShapeDesc() As String
        Get
            Return shapeDesc

        End Get

        Set(ByVal value As String)

            shapeDesc = value

        End Set
    End Property





    '公用的事件模型

    Public Event AskForAddEntity(ByVal ln As String, ByVal ptlist() As MapWinGIS.Point, ByVal shpDesc As String)
    'Public Event AskForAddEntity(ByVal ln As String, ByVal ptlist() As MapWinGIS.Point)
    Public Event AskForRemoveEntity(ByVal ln As String, ByVal sn As String)
    Public Event EntitySelected(ByVal ln As String, ByVal sn As String)
    Public Event AskForMove(ByVal ln As String, ByVal sn As String(), ByVal mxx As Double, ByVal myy As Double)

    ' Public Event AskForModifyEntity(ByVal ln As String, ByVal sn As String, ByVal ptlist() As MapWinGIS.Point, ByVal desc As String)

    '私有的一些函数，用于重写和爆发事件
    Private Sub EntityDrawEnd(ByVal d As Double)

        '如果当前层处于隐藏状态，那么直接返回
        If Not mapwin.get_LayerVisible(m_iLayer) Then
            Return
        End If

        Dim n As Integer = m_drawTool.OperShapeProperty.plist.Count




        Dim ptlist(n - 1) As MapWinGIS.Point

        For i As Integer = 1 To n
            Dim pi As Drawing.PointF = m_drawTool.OperShapeProperty.plist(i - 1)
            Dim pt As New MapWinGIS.Point


            mapwin.PixelToProj(pi.X, pi.Y, pt.x, pt.y)

            ptlist(i - 1) = pt




        Next

        '为了保证正确的返回
        m_drawTool.CancelDraw()


        RaiseEvent AskForAddEntity(lname, ptlist,shapeDesc)

    End Sub

    Private Sub ResetSelect()

        m_selShapes.Clear()


        Dim col As System.Drawing.Color = mapwin.get_ShapeLayerPointColor(m_iLayer)

        Dim col2 As System.Drawing.Color = mapwin.get_ShapeLayerLineColor(m_iLayer)

        Dim col3 As System.Drawing.Color = mapwin.get_ShapeLayerFillColor(m_iLayer)



        Dim originalColor As UInt32 = col.B * 256 * 256 + col.G * 256 + col.R

        Dim originalColor2 As UInt32 = col2.B * 256 * 256 + col2.G * 256 + col2.R

        Dim originalColor3 As UInt32 = col3.B * 256 * 256 + col3.G * 256 + col3.R



        mapwin.set_ShapeLayerPointColor(m_iLayer, originalColor)

        mapwin.set_ShapeLayerLineColor(m_iLayer, originalColor2)
        mapwin.set_ShapeLayerFillColor(m_iLayer, originalColor3)



    End Sub

    Public Enum SelectShapeMode
        INCLUSION

        INTERSECTION

    End Enum


    Protected selMode As SelectShapeMode = SelectShapeMode.INCLUSION


    <CategoryAttribute("选择模型"), _
  DisplayName("物体选择模式")> _
  Public Property SelectMode() As SelectShapeMode
        Get
            Return selMode
        End Get
        Set(ByVal value As SelectShapeMode)

            selMode = value

        End Set
    End Property
    Private Function SelectShapes() As Integer()
        Dim selectedshapes() As Integer

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)
        '只选择可见层
        If mapwin.get_LayerVisible(m_iLayer) Then


            If SelectMode = SelectShapeMode.INCLUSION Then

                If sf.SelectShapes(m_Exents, 0, MapWinGIS.SelectMode.INCLUSION, selectedshapes) = True Then

                    Dim I As Integer



                    For I = 0 To selectedshapes.Length - 1
                        ' since the select box is smaller than the map, we already know the shapes selected are in the right place.
                        ' This tests each shape to make sure that they have not had their "visible" property set to false.
                        If mapwin.get_ShapeVisible(m_iLayer, selectedshapes(I)) Then





                            mapwin.set_ShapeFillColor(m_iLayer, selectedshapes(I), m_SColor)
                            mapwin.set_ShapePointColor(m_iLayer, selectedshapes(I), m_SColor)
                            mapwin.set_ShapeLineColor(m_iLayer, selectedshapes(I), m_SColor)

                        End If

                    Next




                End If

            Else

                If sf.SelectShapes(m_Exents, 0, MapWinGIS.SelectMode.INTERSECTION, selectedshapes) = True Then

                    Dim I As Integer



                    For I = 0 To selectedshapes.Length - 1
                        ' since the select box is smaller than the map, we already know the shapes selected are in the right place.
                        ' This tests each shape to make sure that they have not had their "visible" property set to false.
                        If mapwin.get_ShapeVisible(m_iLayer, selectedshapes(I)) Then





                            mapwin.set_ShapeFillColor(m_iLayer, selectedshapes(I), m_SColor)
                            mapwin.set_ShapePointColor(m_iLayer, selectedshapes(I), m_SColor)
                            mapwin.set_ShapeLineColor(m_iLayer, selectedshapes(I), m_SColor)

                        End If

                    Next




                End If

            End If





        End If


        Return selectedshapes

    End Function

    Protected Function GetShapeFieldString(ByVal iShape As Integer, ByVal iIndex As Integer) As String

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

        If iShape >= sf.NumShapes Then
            Return ""
        End If

        Return sf.CellValue(iIndex, iShape).ToString()

    End Function
    Protected Function GetShapeIdByFieldString(ByVal sn As String, ByVal iIndex As Integer) As Integer
        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

        For i As Integer = 0 To sf.NumShapes - 1
            If sf.CellValue(iIndex, i).ToString() = sn Then
                Return i
            End If

        Next

        Return -1


    End Function

    Protected Function GetShapePointsByFieldString(ByVal sn As String, ByVal iIndex As Integer) As MapWinGIS.Point()
        Dim iShape As Integer = Me.GetShapeIdByFieldString(sn, iIndex)
        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

        Dim n As Integer = sf.Shape(iShape).numPoints
        Dim pts(n - 1) As MapWinGIS.Point
        For i As Integer = 0 To n - 1
            pts(i) = sf.QuickPoint(iShape, i)

        Next

        Return pts

    End Function

    '用于继承上一层事件的函数
    Public Overrides Sub mapMain_DblClick(ByVal sender As System.Object, ByVal e As System.EventArgs)
        If m_bReadOnly Then
            Return
        End If

        If m_bEditing Then
            m_drawTool.superMouseDblClick(sender, e)

        End If

    End Sub

    Public Overrides Sub mapMain_PreviewKeyDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.PreviewKeyDownEventArgs)
        If m_bReadOnly Then
            Return
        End If


        '删除事件的产生,这里需要定义一个临时集合，借此保证主集合的修改不影响已经发生的事件
        If e.KeyCode = System.Windows.Forms.Keys.Delete Then

            Dim selTemps As New List(Of String)

            selTemps.AddRange(m_selShapes)

            For Each str As String In selTemps


                RaiseEvent AskForRemoveEntity(lname, str)
            Next



        End If


        If m_bEditing Then

            If e.KeyCode = System.Windows.Forms.Keys.Escape Then

                If m_drawTool.IsOnDrawing() Then
                    m_drawTool.CancelDraw()
                    mapwin.Redraw()

                Else
                    '使当前处理对象恢复无编辑状态

                    Me.SetDrawEntity(False)

                End If



            End If

        End If
    End Sub

    Public Overrides Sub mapMain_MouseUpEvent(ByVal sender As System.Object, ByVal e As AxMapWinGIS._DMapEvents_MouseUpEvent)
        If m_bReadOnly Then
            Return
        End If

        If m_bEditing Then

            m_drawTool.superMouseUp(sender, e)

        End If
    End Sub

    Public Overrides Sub mapMain_MouseMoveEvent(ByVal sender As System.Object, ByVal e As AxMapWinGIS._DMapEvents_MouseMoveEvent)
        If m_bReadOnly Then
            Return
        End If


        If m_bEditing Then
            m_drawTool.superMouseMove(sender, e)

        End If
    End Sub

    Public Overrides Sub mapMain_MouseDownEvent(ByVal sender As System.Object, ByVal e As AxMapWinGIS._DMapEvents_MouseDownEvent)

        '仅在左键点击的时候进行处理
        If e.button = 1 Then

            If mapwin.CursorMode = MapWinGIS.tkCursorMode.cmSelection Then
                Me.ResetSelect()
            End If

        End If

       



        If m_bReadOnly Then
            Return
        End If

        '右键不计算在内

        If m_bEditing Then
            m_drawTool.superMouseDown(sender, e)


        End If
    End Sub

    Public Overrides Sub mapMain_SelectBoxFinal(ByVal sender As System.Object, ByVal e As AxMapWinGIS._DMapEvents_SelectBoxFinalEvent)
        Me.ResetSelect()

        If m_bReadOnly Then
            Return
        End If


        Dim top, left, bottom, right As Double

        ' Change the extents into geographic coordinates
        mapwin.PixelToProj(e.left, e.bottom, left, bottom)
        mapwin.PixelToProj(e.right, e.top, right, top)

        ' Set the region to control
        m_Exents.SetBounds(left, bottom, 0, right, top, 0)

        '将选择方法封装起来
        Dim shapes() As Integer

        shapes = Me.SelectShapes()

        If shapes.Length > 0 Then

            For i As Integer = 0 To shapes.Length - 1

                Dim iShape As Integer = shapes(i)
                Dim str As String = Me.GetShapeFieldString(iShape, 0)

                If str <> "" Then

                    m_selShapes.Add(str)
                    RaiseEvent EntitySelected(lname, str)
                End If

            Next


        End If





    End Sub


    '初始化啦，需要第一个被调用，构造函数除外,且此函数只能被调用一次
    Public Overrides Sub InitLayer(ByRef m As AxMapWinGIS.AxMap)



        '不能序列化的，只好从新初始化了

        mapwin = m
        m_Exents = New MapWinGIS.Extents


        '与之对应的一些变量,只有在这里才是有效的，哈哈哈啊，被你搞死了
        m_drawTool.SetMapRef(mapwin)

        '给一些变量更改值



        '还好拥有共同的特征
        Dim sf As New MapWinGIS.Shapefile()
        sf.Open(fname)
        m_iLayer = mapwin.AddLayer(sf, True)

        mapwin.set_LayerKey(m_iLayer, lname)






        '现在可以更新自己的所有属性了
        InitBaseProp()

        InitProp()




    End Sub

    '保存和加载
    Public Overrides Sub Save()

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

        sf.StartEditingShapes()

        Dim cb As New GCallback
        Dim bS As Boolean = sf.Save(cb)

        sf.StopEditingShapes()


        If bS Then

        Else


            System.Windows.Forms.MessageBox.Show("文件保存错误，请查看相应权限!")

        End If

    End Sub

    Public Overrides Sub SaveAs(ByVal strPath As String)

        Dim fn As String = strPath + lname + ".shp"

        Dim myPath(2) As String
        myPath(0) = strPath + lname + ".shp"
        myPath(1) = strPath + lname + ".dbf"
        myPath(2) = strPath + lname + ".shx"


        For i As Integer = 0 To myPath.Length - 1
            If System.IO.File.Exists(myPath(i)) Then
                Try
                    System.IO.File.SetAttributes(myPath(i), IO.FileAttributes.Normal)
                    System.IO.File.Delete(myPath(i))
                Catch ex As Exception

                End Try

            End If
        Next

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)

        Dim bS As Boolean = sf.SaveAs(fn)

        If Not bS Then
            System.Windows.Forms.MessageBox.Show("文件保存错误，请查看相应权限!")

        End If

        '这个时候文件句柄已经改变，所以需要取回原来的句柄
        Dim b As Boolean = sf.Open(fname)
        If Not b Then
            System.Windows.Forms.MessageBox.Show("回读文件失败，请不要删除或更改项目文件!")

        End If

    End Sub

    Public Overrides Sub ReLoad(ByRef m As AxMapWinGIS.AxMap, ByVal fPath As String)

        fname = fPath + lname + ".shp"

        Me.InitLayer(m)


    End Sub

    Public Overrides Sub Dispose()

        Dim sf As MapWinGIS.Shapefile = mapwin.get_GetObject(m_iLayer)
        sf.Close()

    End Sub

    ''' <summary>
    ''' 移动被选中的shape，根据偏移量
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub AskMoveSelShapes(ByVal xOffset As Double, ByVal yOffset As Double)

        '代码优化，一层发送一次
        If m_selShapes.Count > 0 Then

            'Dim pts As MapWinGIS.Point()


            Dim strReturn() As String = m_selShapes.ToArray()
            RaiseEvent AskForMove(lname, strReturn, xOffset, yOffset)






        End If

    End Sub

    Public Function GetSelectedShapes() As List(Of String)


        Return m_selShapes

        'If m_selShapes.Count > 0 Then

        '    'Dim pts As MapWinGIS.Point()


        '    Dim strReturn() As String = m_selShapes.ToArray()

        '    Return strReturn

        'Else

        '    Return Nothing



        'End If

    End Function

    ''' <summary>
    ''' z只在point,polyline,polygon 有作用
    ''' </summary>
    ''' <remarks></remarks>
    Public Overridable Sub BuildKeyPtsFromFile()

    End Sub



End Class
